import random
import traceback

import redis
from curl_cffi import requests
# import requests
from flask_restful import Resource, fields, marshal_with, request, reqparse
from werkzeug.datastructures import FileStorage
import view.common as view_common
import service.web_service as service
import service.generate_data_service as generate_service
from exception.api_exception import APIException
import view.submit as v_submit
from utils.common.jwt_middleware import jwt_required, get_jwt_identity, all_jwt_required, get_jwt
from dao import resource_dao, user_resource_dao
from flask import make_response, send_file
import tempfile
import time
from utils.common.redis_client import Redis


class JwtTest(Resource):
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    # @jwt_required()
    @all_jwt_required()
    @marshal_with(res_obj)
    def post(self):
        current_user = get_jwt_identity()
        jwt_info = get_jwt()
        res = {'user': current_user, 'jwt_info': jwt_info}
        return view_common.success(res=res)


class AuthResource(Resource):
    """
    当前用户的权限接口
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            current_user = get_jwt_identity()
            user_id = current_user['id']
            user_resources = user_resource_dao.search_by_user_id(user_id)
            if not user_resources or len(user_resources) <= 0:
                return view_common.success(res={})
            resource_ids = [i.resource_id for i in user_resources]
            resources = resource_dao.search_by_resource_ids(resource_ids)
            res = []
            for i in resources:
                res.append({'resource_code': i.resource_code, 'resource_name': i.resource_name})
        except Exception:
            raise APIException(message="请求失败", code=500)
        return view_common.success(res=res)


class Register(Resource):
    """
    注册
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    def post(self):
        try:
            data = request.get_json()
            obj = v_submit.RegisterView.model_validate(data)
        except Exception:
            raise APIException(message="请求失败", code=500)
        if not obj or obj.user_name == "" or obj.password == "":
            raise APIException(message="用户名或密码为空", code=500)
        res = service.register(obj)
        return view_common.success(res=res)
    
class ModifyPwd(Resource):
    """
    修改密码
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    def post(self):
        try:
            data = request.get_json()
            obj = v_submit.ModifyPwdView.model_validate(data)
        except Exception:
            raise APIException(message="请求失败", code=500)
        if not obj or obj.user_name == "" or obj.old_pwd == "" or obj.new_pwd == '':
            raise APIException(message="用户名或密码为空", code=500)
        res = service.modifyPwd(obj)
        return view_common.success(res=res)


class Login(Resource):
    """
    登录
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    def post(self):
        try:
            data = request.get_json()
            obj = v_submit.UserView.model_validate(data)
        except Exception:
            raise APIException(message="入参错误", code=500)
        res = service.login(obj)
        return view_common.success(res=res)


class Receiving(Resource):
    """
    接单
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
            current_user = get_jwt_identity()
            user_id = current_user['id']
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.receiving(work_order_id, user_id)
        return view_common.success(res=res)


class MakeDataV2(Resource):
    """
        生成基础result数据
        """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.make_datas_v2(work_order_id, data)
        return view_common.success(res=res)


class MakeData(Resource):
    """
    生成基础result数据
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.make_datas(work_order_id, data)
        return view_common.success(res=res)


class ExplainLink(Resource):
    """
    解析链接
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            data = request.args
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.explain_link(work_order_id)
        return view_common.success(res=res)


class JudgeConfig(Resource):
    """
    解析链接
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
            make_data = data.get("make_data")
            view_config_data = data.get("view_config_data")
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.judge_config(work_order_id, make_data, view_config_data)
        return view_common.success(res=res)


class ReloadLink(Resource):
    """
        解析链接
        """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            data = request.args
            work_order_id = int(data.get("work_order_id"))
            link = data.get("link")
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.reload_link(work_order_id, link)
        return view_common.success(res=res)


class ExplainLinkV2(Resource):
    """
    解析链接
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            data = request.args
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.explain_link_v2(work_order_id)
        return view_common.success(res=res)


class WorkOrderInfo(Resource):
    """
    查询工单详情
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            work_order_id = int(request.args.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res = service.work_order_info(work_order_id)
        return view_common.success(res=res)


class ChangeOrderInfo(Resource):
    """
       修改工单信息-全部字段
       """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        data = request.get_json()
        work_order_id_str = data.get("id")
        if not work_order_id_str:
            raise APIException(message="work_order_id is null")
        service.change_order_info(data)
        return view_common.success(res=None)


class ChangeOrderStatus(Resource):
    """
    修改工单信息
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        data = request.args
        work_order_id_str = data.get("work_order_id")
        if work_order_id_str is None or work_order_id_str == "":
            raise APIException(message="work_order_id is null")
        work_order_id = int(work_order_id_str)
        modify_type_str = data.get("modify_type")
        if modify_type_str is None or modify_type_str == "":
            raise APIException(message="modify_type_str is null")
        modify_type = int(modify_type_str)
        b = service.change_order_status(work_order_id, modify_type, data)
        return view_common.success(res=None) if b else view_common.failed_10001(res=None)


class SearchResultV2(Resource):
    """
        查询当前工单的答案
        """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            data = request.args
            work_order_id = int(data.get("work_order_id"))
            status = int(data.get("status"))
        except Exception as e:
            traceback.print_exc()
            raise APIException("解析参数失败")
        res = service.search_result_v2(work_order_id, status)
        return view_common.success(res=res)


class SearchResult(Resource):
    """
    查询当前工单的答案
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        try:
            data = request.args
            work_order_id = int(data.get("work_order_id"))
            status = int(data.get("status"))
        except Exception as e:
            traceback.print_exc()
            raise APIException("解析参数失败")
        res = service.search_result(work_order_id, status)
        return view_common.success(res=res)


class InsertResult(Resource):
    """
    写入答案-线上不可用
    """
    res = {
        'id': fields.Integer,
        'status': fields.Integer
    }
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.List(fields.Nested(res))
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        data = request.get_json()
        work_order_id_str = data.get("work_order_id")
        if work_order_id_str is None or work_order_id_str == "":
            return view_common.failed_10001(res={"work_order_id is null or ''"})
        work_order_id = int(work_order_id_str)
        res = service.insert_result(work_order_id)
        return view_common.success(res=res)


class SearchSubmitConfig(Resource):
    """
    查询提交相关配置
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res, message = service.search_submit_config(work_order_id)
        return view_common.success_message(res=res, message=message)


class SearchRelationConfig(Resource):
    """
     查询提交相关配置
     """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res, message = service.search_relation_config(work_order_id)
        return view_common.success_message(res=res, message=message)


class SearchProgramme(Resource):
    """
    查询方案
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        try:
            data = request.get_json()
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="解析参数错误" + str(e))
        res, message = service.search_programme(work_order_id)
        return view_common.success_message(res=res, message=message)


class SaveProgramme(Resource):
    """
    保存方案
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        data = request.get_json()
        if data is None:
            return view_common.failed_10001(res="保存失败，内容为空")
        wo_id = data.get('work_order_id')  # 工单id
        programmes = data.get('weights')  # 具体策略数据
        res = service.save_programme(wo_id, programmes)
        return view_common.success(res=res)


class SearchProgrammeWeight(Resource):
    """
    查询策略
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        data = request.get_json()
        work_order_id_str = data.get("work_order_id")
        if work_order_id_str is None or work_order_id_str == "":
            return view_common.failed_10001(res={"工单不存在"})
        work_order_id = int(work_order_id_str)
        res, message = service.search_programme_weight(work_order_id)
        return view_common.success_message(res=res, message=message)


class SaveProgrammeWeight(Resource):
    """
    保存策略
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def post(self):
        data = request.get_json()
        if data is None:
            return view_common.failed_10001(res="保存失败，内容为空")
        wo_id = data.get('work_order_id')  # 工单id
        weights = data.get('weights')  # 具体策略数据
        res = service.save_programme_weight(wo_id, weights)
        return view_common.success(res=res)


class GetFrequency(Resource):
    """
    查询频数分析结果
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    @all_jwt_required()
    def get(self):
        data = request.args
        work_order_id_str = data.get('work_order_id')
        if work_order_id_str is None:
            raise APIException(message="请求参数错误,工单id不存在", code=500)
        work_order_id = int(work_order_id_str)
        res = service.get_frequency(work_order_id)
        return view_common.success(res=res)


class ModifyResultById(Resource):
    """
    修改答案-通过答案id
    """
    res = {
        'id': fields.Integer,
        'status': fields.Integer
    }
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.List(fields.Nested(res))
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def post(self):
        data = request.get_json()
        work_order_id_str = data.get("work_order_id")
        if work_order_id_str is None or work_order_id_str == "":
            return view_common.failed_10001(res={"topic_id is null or ''"})
        work_order_id = int(work_order_id_str)
        res = service.modify_result_by_id(work_order_id, data.get("data"))
        return view_common.success(res=res)


class RelationConfirm(Resource):
    """
    确认结果到基础数据
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def post(self):
        data = request.get_json()
        work_order_id_str = data.get("work_order_id")
        if work_order_id_str is None or work_order_id_str == "":
            return view_common.failed_10001(res={"work_order_id is null or ''"})
        work_order_id = int(work_order_id_str)
        res = service.relation_confirm(work_order_id)
        return view_common.success(res=res)


class RelateTopic(Resource):
    """
    获取数据库索引数据对应的标题
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def get(self):
        data = request.args
        work_order_id_str = data.get('work_order_id')
        if work_order_id_str is None:
            return view_common.failed_10001(res="工单id为空")
        work_order_id = int(work_order_id_str)
        res = service.relate_topic(work_order_id)
        return view_common.success(res=res)


class RelationCalculate(Resource):
    """
    仅计算相关性结果
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def post(self):
        try:
            data = request.get_json()
            obj = v_submit.RelationView()
            obj.work_order_id = int(data.get("work_order_id"))
            obj.correlation = data.get("correlation")
            obj.do_ra = bool(data.get("do_ra"))
            obj.do_va = bool(data.get("do_va"))
            obj.do_ca = bool(data.get("do_ca"))
            obj.do_fa = bool(data.get("do_fa"))
            obj.do_re = bool(data.get("do_re"))
            obj.re_v = data.get("re_v")
            obj.re_dv = data.get("re_dv")
            obj.kmo_min = float(data.get("kmo_min"))  # kmo最小值
            obj.kmo_max = float(data.get("kmo_max"))  # kmo最大值
            obj.regressive_r = float(data.get("regressive_r"))  # 回归r方
        except Exception as e:
            raise APIException(message="参数错误" + str(e))
        # 保存相关的配置
        service.save_relation_config(obj.work_order_id, data)
        res = service.relation_calculate(obj)
        return view_common.success(res=res)


class RelationStop(Resource):
    """
    生成数据-相关性数据（及相关性算法答案）
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def get(self):
        try:
            data = request.args
            work_order_id = int(data.get("work_order_id"))
        except Exception as e:
            raise APIException(message="参数错误" + str(e))
        res = service.relation_stop(work_order_id)  # 循环校验
        return view_common.success(res=res)


class Relation(Resource):
    """
    生成数据-相关性数据（及相关性算法答案）
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def post(self):
        data = request.get_json()
        obj = v_submit.RelationView()
        obj.do_re = bool(data.get("do_re"))
        if obj.do_re:  # 如果是回归，两个参数比如大于0
            obj.re_v = data.get("re_v")
            obj.re_dv = data.get("re_dv")
            if not obj.re_v or not obj.re_dv:
                raise APIException(message="请校验回归分析参数")
            obj.re_v = [element for element in obj.re_v if element]
            obj.re_dv = [element for element in obj.re_dv if element]
            if not obj.re_v or not obj.re_dv:
                raise APIException(message="请校验回归分析参数")
        try:
            obj.work_order_id = int(data.get("work_order_id"))
            obj.correlation = data.get("correlation")
            obj.do_ra = bool(data.get("do_ra"))
            obj.do_va = bool(data.get("do_va"))
            obj.do_ca = bool(data.get("do_ca"))
            obj.do_fa = bool(data.get("do_fa"))
            obj.relation_generate_type = data.get("relation_generate_type")
            obj.kmo_min = float(data.get("kmo_min"))  # kmo最小值
            obj.kmo_max = float(data.get("kmo_max"))  # kmo最大值
            obj.regressive_r = float(data.get("regressive_r"))  # 回归r方
        except Exception as e:
            raise APIException(message="参数错误" + str(e))
        # 保存相关的配置
        service.save_relation_config(obj.work_order_id, data)
        # 进行相关性算法操作
        # res = service.relation(obj) # 仅生成一次数据
        res = service.relation_cycle_check(obj)  # 循环校验
        return view_common.success(res=res)


class RelationAnalysisResult(Resource):
    """
    查询相关性分析结果
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @all_jwt_required()
    @marshal_with(res_obj)
    def get(self):
        data = request.args
        work_order_id_str = data.get('work_order_id')
        if work_order_id_str is None:
            return view_common.failed_10001(res="工单id为空")
        work_order_id = int(work_order_id_str)
        res = service.relation_analysis_result(work_order_id)
        return view_common.success(res=res)


class ExportBaseResult(Resource):
    """
    导出基础数据结果
    """

    # @all_jwt_required()
    def get(self):
        data = request.args
        work_order_id_str = data.get('work_order_id')
        view_status = int(data.get('view_status'))
        if not work_order_id_str:
            raise APIException(message="工单id为空")
        work_order_id = int(work_order_id_str)
        res = service.export_base_result(work_order_id, view_status)
        temp_file = tempfile.NamedTemporaryFile(delete=False)
        temp_file.write(res)
        temp_file.close()
        name = str(work_order_id) + '_' + '基础数据答案' + str(int(time.time())) + '.xlsx'
        return send_file(temp_file.name, download_name=name, as_attachment=True)


class UploadBaseResult(Resource):
    """
    上传基础数据结果
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    # @all_jwt_required()
    @marshal_with(res_obj)
    def post(self):
        if 'file_data' not in request.files:
            return '没有文件被上传'
        file_data = request.files['file_data']
        try:
            work_order_id = int(request.args.get('work_order_id'))
        except Exception as e:
            raise APIException(message="工单id为空")
        res = service.upload_base_result(work_order_id, file_data)
        return view_common.success(res=res)


class TestRedis(Resource):
    """
    测试redis
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    def get(self):
        res = "test_redis"
        import datetime
        resend_time_unix = datetime.datetime.now()
        resend_time = resend_time_unix.strftime("%Y-%m-%d %H:%M:%S.%f")  # 生成每组数据的间隔时间(秒)
        Redis.write('test_key', resend_time)
        # 检查客户端是否连接
        # try:
        #     redis_client.ping()
        #     print('Redis client is connected.')
        #     res = 'connected'
        # except redis.exceptions.ConnectionError:
        #     print('Redis client is not connected.')
        #     res = 'not connected'
        return view_common.success(res=res)


class ChangeWorkOrderSize(Resource):
    """
        预览链接
        """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    def post(self):
        try:
            data = request.get_json()
            work_order_id = data.get('work_order_id')
            size = int(data.get('size'))
        except Exception as e:
            raise APIException(message="请求参数错误")
        res = generate_service.change_work_order_size(work_order_id, size)
        return view_common.success(res=res)


class PreviewLink(Resource):
    """
    预览链接
    """
    res_obj = {
        'code': fields.Integer,
        'message': fields.String,
        'result': fields.Raw
    }

    @marshal_with(res_obj)
    def post(self):
        data = request.get_json()
        link = data.get('link')
        res = generate_service.preview_link(link)
        return view_common.success(res=res)
